package com.fqgj.sentry.biz.decision;

import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.fqgj.sentry.common.exception.BizException;
import com.fqgj.sentry.controller.request.EngineRequest;
import com.fqgj.sentry.exception.ErrorCodeEnums;
import com.fqgj.sentry.manage.entity.McApplicationEntity;
import com.fqgj.sentry.manage.entity.McMerchantEntity;
import com.fqgj.sentry.manage.service.ApplicationService;
import com.fqgj.sentry.policy.client.*;
import com.fqgj.sentry.policy.dao.PcColumnDao;
import com.fqgj.sentry.policy.dao.PcRuleColumnDao;
import com.fqgj.sentry.policy.engine.domain.*;
import com.fqgj.sentry.policy.entity.*;
import com.fqgj.sentry.policy.enums.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by liupengpeng on 2017/8/10.
 */
@Service
public class DecisionBusinessV3 {
    public static final Log LOGGER = LogFactory.getLog(DecisionBusinessV3.class);
    public static final Log decisionLogger = LogFactory.getLog("engine-decision-json");
    @Autowired
    private ApplicationService applicationService;
    @Autowired
    private EventService eventService;
    @Autowired
    private PolicySetService policySetService;
    @Autowired
    private RuleService ruleService;
    @Autowired
    private PolicyExecutorService executorService;

    @Autowired
    private PcColumnDao pcColumnDao;

    @Autowired
    private PcRuleColumnDao pcRuleColumnDao;

    //获取当前执行者的下面所有依赖的数据集
    public Set<String> getNeededColumnCodeFromPC(Long policySetsId, Long executorId) {

        List<PcRuleEntity> ruleEntityList = ruleService.findActiveByPolicySetsIdAndExecutorId(policySetsId, executorId);
        if (CollectionUtils.isEmpty(ruleEntityList)) {
            throw new BizException(ErrorCodeEnums.rule_not_exist_error);
        }

        List<Long> ruleIds = new ArrayList<>();
        ruleEntityList.forEach(r -> {
            if (r.getIsActive() == 1) {
                ruleIds.add(r.getId());
            }
        });

        List<PcRuleColumnEntity> byRuleIds = pcRuleColumnDao.findByRuleIds(ruleIds);

        Set<String> columnCodeSet = new HashSet<>();
        byRuleIds.forEach(r -> {
            if (r.getColumnCode() != null) {
                columnCodeSet.add(r.getColumnCode());
            }
        });

        List<PcColumnEntity> pcColumnEntities = pcColumnDao.selectListByColumCodes(columnCodeSet);
        Set<String> columnCodeSetNeed = new HashSet<>();
        pcColumnEntities.forEach(c -> {
            if (c.getStatus() != 3) {
                columnCodeSetNeed.add(c.getColumnCode());
            }
        });

        return columnCodeSetNeed;
    }

    /**
     * 获取策略集下面实际使用的数据集code列表
     */
    public Set<String> getPolicySetsDataModules(EngineRequest request) {
        //  冠军者  挑战者 逻辑  2、json 获取
        PolicySet policySet = getPolicySet(false, request.getMerchantCode(), request.getAppCode(), request.getEventCode());
        if (policySet == null) {
            return null;
        }

        return getNeededColumnCodeFromPC(policySet.getPolicySetId(), policySet.getExecutorId());
    }


    private PolicySet getPolicySet(Boolean verify, String merchantCode, String appCode, String eventCode) {
        //查询策略集
        McMerchantEntity merchantEntity = applicationService.selectMerchantByMerchantCode(merchantCode);
        if (merchantEntity == null) {
            LOGGER.error("商户不存在,code:{}", merchantCode);
            throw new BizException(ErrorCodeEnums.merchant_not_exists_error);
        }
        McApplicationEntity applicationEntity = applicationService.selectByMerchantIdAndAppCode(merchantEntity.getId(), appCode);
        if (applicationEntity == null) {
            throw new BizException(ErrorCodeEnums.application_not_exists_error);
        }
        PcEventEntity eventEntity = eventService.selectByMerchantIdAndCode(merchantEntity.getId(), eventCode);
        if (eventEntity == null) {
            throw new BizException(ErrorCodeEnums.event_not_exists_error);
        }
        PcPolicySetsEntity policySetsEntity = policySetService.selectByAppIdAndEventId(applicationEntity.getId(), eventEntity.getId());
        if (policySetsEntity == null) {
            throw new BizException(ErrorCodeEnums.policy_set_not_exist_error);
        }


        //执行者
        PcExecutorEntity championExecutor = executorService.selectPcExecutorCurrent(policySetsEntity.getId(), ExecutorTypeEnum.champion.getType(), ActiveEnum.active.getType());
        PcExecutorEntity challengerExecutor = executorService.selectPcExecutorCurrent(policySetsEntity.getId(), ExecutorTypeEnum.challenger.getType(), ActiveEnum.active.getType());
        PcExecutorEntity verifierExecutor = executorService.selectPcExecutorCurrent(policySetsEntity.getId(), ExecutorTypeEnum.verifier.getType(), ActiveEnum.active.getType());

        Long executorId = null;

        if (!verify) {
            if (championExecutor == null && challengerExecutor == null) {
                throw new BizException(ErrorCodeEnums.executor_not_exist_error);
            }
            //筛选要执行则 执行者
            if (challengerExecutor == null && championExecutor != null) {
                executorId = championExecutor.getId();
            }
            if (challengerExecutor != null && championExecutor != null) {
                //查询 占比
                Integer executePercent = challengerExecutor.getExecutePercent();
                if (executePercent > 0) {
                    int randNum = new Random().nextInt(100) + 1;
                    if (randNum <= executePercent) {
                        executorId = challengerExecutor.getId();
                    } else {
                        executorId = championExecutor.getId();
                    }
                } else {
                    executorId = championExecutor.getId();
                }
            }
        } else {
            if (verifierExecutor != null) {
                executorId = verifierExecutor.getId();
            } else {
                return null;
            }
        }

        if (executorId == null) {
            throw new BizException(ErrorCodeEnums.executor_not_exist_error);
        }


        //根据 执行者 拿缓存json
        return new PolicySet().setPolicySetId(policySetsEntity.getId()).setExecutorId(executorId);
    }

}
